package factroy

import (
	"fucker/frame/config"
	"fucker/frame/context"
	"fucker/frame/execute"
	"fyne.io/fyne/v2"
	"fyne.io/fyne/v2/container"
	"fyne.io/fyne/v2/data/binding"
	"fyne.io/fyne/v2/data/validation"
	"fyne.io/fyne/v2/widget"
	"log"
)

func Create(name *config.Child) interface{} {
	log.Println("create " + name.Type + "key:" + name.Key)
	if name.Type == "widget" {

		return createWight(name)
	}

	if name.Type == "layout" {
		return createLayout(name, nil)
	}

	panic("not support type")
}

func CreateWithChild(name *config.Child, sub []fyne.CanvasObject) interface{} {
	log.Println("create " + name.Type + "key:" + name.Key)
	if name.Type == "widget" {

		return createWight(name)
	}

	if name.Type == "layout" {
		return createLayout(name, sub)
	}

	panic("not support type")
}

func createLayout(w *config.Child, sub []fyne.CanvasObject) interface{} {
	switch w.Key {
	case "vbox":
		return createVbox(w)
		break
	case "hbox":
		return createHbox(w)
		break
	case "grid":
		return createGrid(w)
		break
	case "vscroll":
		return createVScroll(w, sub)
		break
	case "hscroll":
		return createhScroll(w, sub)
		break
	case "hsplit":
		return createhSplit(w, sub)
		break
	case "vsplit":
		return createVSplit(w, sub)
	case "tab":
		return createTab(w, sub)
	case "border":
		return createBorder(w, sub)
		break
	case "cust":
		return createCust(w)
		break
	}

	return nil
}

func createBorder(w *config.Child, sub []fyne.CanvasObject) interface{} {
	border := container.NewBorder(sub[0], sub[1], sub[2], sub[3])
	return border
}

func createTab(w *config.Child, sub []fyne.CanvasObject) interface{} {
	//TODO
	return nil
}

func createVSplit(w *config.Child, sub []fyne.CanvasObject) interface{} {
	split := container.NewVSplit(sub[0], sub[1])

	if w.Attr != nil && w.Attr.Offset > 0 {
		split.SetOffset(w.Attr.Offset)
	}

	return split
}

func createhSplit(w *config.Child, sub []fyne.CanvasObject) interface{} {
	split := container.NewHSplit(sub[0], sub[1])

	if w.Attr != nil && w.Attr.Offset > 0 {
		split.SetOffset(w.Attr.Offset)
	}

	return split
}

func createCust(w *config.Child) *fyne.Container {

	if w.Function != nil && w.Function.FuncName != "" {
		return execute.ExecNativeCustContainer(w.Function.FuncName, nil)
	}

	return nil
}

func createhScroll(w *config.Child, sub []fyne.CanvasObject) *container.Scroll {
	return container.NewHScroll(sub[0])
}

func createVScroll(w *config.Child, sub []fyne.CanvasObject) *container.Scroll {
	return container.NewVScroll(sub[0])
}

func createGrid(w *config.Child) *fyne.Container {
	grid := container.NewAdaptiveGrid(w.Attr.Row)

	return grid
}

func createButton(w *config.Child) *widget.Button {
	button := widget.NewButton(w.Attr.Text, func() {
		if w.Function != nil {

			if w.Function.Type == "js" {
				if w.Function.Script != "" {
					execute.ExecJsScript(w.Function.FuncName, w.Function.Script, w.Function.Param)
				} else {
					execute.ExecJs(w.Function.FuncName, w.Function.Param)
				}

				return
			}

			if w.Function.Type == "go" || w.Function.Type == "" {
				if w.Function.FuncName != "" {
					execute.ExecNative(w.Function.FuncName, w.Function.Param)
				}
				return
			}
		}
	})

	return button
}

func createHbox(w *config.Child) *fyne.Container {
	return container.NewHBox()
}

func createVbox(w *config.Child) *fyne.Container {
	return container.NewVBox()
}

func createWight(w *config.Child) fyne.CanvasObject {
	switch w.Key {
	case "label":
		return createLabel(w)
		break
	case "entry":
		return createInput(w)
		break
	case "button":
		return createButton(w)
		break
	case "sep":
		return createSep(w)
	case "mentry":
		return createMEntry(w)
		break
	}

	return nil
}

func createMEntry(w *config.Child) fyne.CanvasObject {
	entry := widget.NewMultiLineEntry()

	if w.Attr != nil {
		if w.Attr.Row > 0 {
			entry.SetMinRowsVisible(w.Attr.Row)
		}

		if w.Attr.Ph != "" {
			entry.SetPlaceHolder(w.Attr.Ph)
		}

		if w.Attr.Text != "" {
			entry.SetText(w.Attr.Text)
		}
	}
	return entry
}

func createSep(w *config.Child) fyne.CanvasObject {
	separator := widget.NewSeparator()
	return separator
}

func createInput(w *config.Child) *widget.Entry {

	var entry *widget.Entry

	if w.IsContext && w.Id != "" {
		newString := binding.NewString()

		entry = widget.NewEntryWithData(newString)
		if w.Attr != nil && w.Attr.Text != "" {
			newString.Set(w.Attr.Text)
		}

		context.WContext.Put(w.Id, context.NewBindContext(newString, entry, w.Id, w.IsContext))
	} else {
		entry = widget.NewEntry()
	}

	if w.Change != "" {
		entry.SetOnValidationChanged(func(err error) {
			execute.ExecNative(w.Change, nil)
		})
	}

	if w.Validate != nil {

		if w.Validate.Reg != "" {
			entry.Validator = validation.NewRegexp(w.Validate.Reg, w.Validate.Tips)
		}
	}

	if w.Attr != nil {
		if w.Attr.Row > 0 {
			entry.SetMinRowsVisible(w.Attr.Row)
		}

		if w.Attr.Ph != "" {
			entry.SetPlaceHolder(w.Attr.Ph)
		}

		if w.Attr.Text != "" {
			entry.SetText(w.Attr.Text)
		}
	}

	return entry
}

func createLabel(w *config.Child) *widget.Label {

	var l *widget.Label
	if w.IsContext {
		newString := binding.NewString()

		l = widget.NewLabelWithData(newString)

		context.WContext.Put(w.Id, context.NewBindContext(newString, l, w.Id, w.Save))
	} else {
		l = widget.NewLabel(w.Attr.Text)
	}

	return l
}
